package com.project.school_flate.serviceimpl.shop;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.relation.RelationManager;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.project.school_flate.dto.shop.ShopSaveUserDto;
import com.project.school_flate.entity.com.ComPayFlow;
import com.project.school_flate.entity.com.ComVariable;
import com.project.school_flate.entity.com.table.ComVariableTableDef;
import com.project.school_flate.entity.flow.FlowBusiness;
import com.project.school_flate.entity.flow.FlowMoney;
import com.project.school_flate.entity.flow.FlowTask;
import com.project.school_flate.entity.flow.table.FlowMoneyTableDef;
import com.project.school_flate.entity.shop.ShopInfo;
import com.project.school_flate.entity.shop.ShopSaveUser;
import com.project.school_flate.entity.shop.ShopSaveUser;
import com.project.school_flate.entity.shop.table.ShopRuleTableDef;
import com.project.school_flate.entity.shop.table.ShopSaveUserTableDef;
import com.project.school_flate.entity.user.UserInfo;
import com.project.school_flate.entity.user.table.UserInfoTableDef;
import com.project.school_flate.mapper.com.ComVariableMapper;
import com.project.school_flate.mapper.flow.FlowBusinessMapper;
import com.project.school_flate.mapper.flow.FlowMoneyMapper;
import com.project.school_flate.mapper.flow.FlowTaskMapper;
import com.project.school_flate.mapper.shop.ShopSaveUserMapper;
import com.project.school_flate.mapper.user.UserInfoMapper;
import com.project.school_flate.service.com.WeiXinPayService;
import com.project.school_flate.service.shop.ShopSaveUserService;
import com.project.school_flate.util.PoToDTO;
import com.project.school_flate.util.Result.Result;
import com.project.school_flate.util.system.ComVariableUtil;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  服务层实现。
 *
 * @author 马维健
 * @since 2024/1/2
 */
@Service
public class ShopSaveUserServiceImpl extends ServiceImpl<ShopSaveUserMapper, ShopSaveUser> implements ShopSaveUserService {

    @Autowired
    private ShopSaveUserMapper oShopSaveUserMapper;

    @Autowired
    private FlowBusinessMapper oFlowBusinessMapper;

    @Autowired
    private FlowMoneyMapper oFlowMoneyMapper;

    @Autowired
    private UserInfoMapper oUserInfoMapper;

    @Autowired
    private ComVariableMapper oComVariableMapper;

    @Autowired
    private FlowTaskMapper oFlowTaskMapper;

    @Autowired
    private WeiXinPayService oWeiXinPayService;

    /**
     * 获取店铺用户储蓄
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getShopSaveUser(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        List<ShopSaveUser> oShopSaveUserList = new ArrayList<>();
        long total = 0;
        QueryWrapper queryWrapper = new QueryWrapper();
        //判断是否传入用户ID
        if(StringUtils.isNotBlank(oShopSaveUserDto.getUserId())){
            queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.USER_ID.eq(oShopSaveUserDto.getUserId()));
        }
        //判断是否传入店铺ID
        if(StringUtils.isNotBlank(oShopSaveUserDto.getShopId())){
            queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.SHOP_ID.eq(oShopSaveUserDto.getShopId()));
        }
        //判断是否传入查询时间
        if(oShopSaveUserDto.getQueryBeginTime() != null && oShopSaveUserDto.getQueryEndTime() != null){
            queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.CREATE_TIME.between(oShopSaveUserDto.getQueryBeginTime(),oShopSaveUserDto.getQueryEndTime()));
        }
        //判断是否传入用户名
        if(StringUtils.isNotBlank(oShopSaveUserDto.getUserName())){
            QueryWrapper qwUserInfo = new QueryWrapper();
            qwUserInfo.where(UserInfoTableDef.USER_INFO.NAME.like(oShopSaveUserDto.getUserName()));
            qwUserInfo.where(UserInfoTableDef.USER_INFO.STATE.eq(1));
            List<UserInfo> oUserInfoList = oUserInfoMapper.selectListByQuery(qwUserInfo);
            if(CollectionUtil.isNotEmpty(oUserInfoList)){
                List<String> oUserInfoIdList = new ArrayList<>();
                oUserInfoList.forEach(item->{oUserInfoIdList.add(item.getId());});
                queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.USER_ID.in(oUserInfoIdList));
            }
        }
        queryWrapper.orderBy("create_time desc");
        //是否分页
        if(oShopSaveUserDto.getPage() != null && oShopSaveUserDto.getLimit() != null){
            Page<ShopSaveUser> ShopSaveUserPage = oShopSaveUserMapper.paginateWithRelations(oShopSaveUserDto.getPage(),oShopSaveUserDto.getLimit(),queryWrapper);
            oShopSaveUserList = ShopSaveUserPage.getRecords();
            total = ShopSaveUserPage.getTotalRow();
        }else{
            oShopSaveUserList = oShopSaveUserMapper.selectListWithRelationsByQuery(queryWrapper);
            total = oShopSaveUserList.size();
        }
        //PoToDto
        List<ShopSaveUserDto> oShopSaveUserDtoList = (List<ShopSaveUserDto>) PoToDTO.poToDtoList(oShopSaveUserList,new ShopSaveUserDto());
        return Result.ok(oShopSaveUserDtoList,total);
    }

    /**
     * 添加店铺用户储蓄
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result addShopSaveUser(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        ShopSaveUser oShopSaveUser = new ShopSaveUser();
        PoToDTO.poToDto(oShopSaveUserDto,oShopSaveUser);
        if(oShopSaveUserMapper.insert(oShopSaveUser) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("添加店铺用户储蓄失败");
        }
        return Result.ok("添加店铺用户储蓄成功");
    }

    /**
     * 修改店铺用户储蓄
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result updateShopSaveUser(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        ShopSaveUser oShopSaveUser = new ShopSaveUser();
        PoToDTO.poToDto(oShopSaveUserDto,oShopSaveUser);
        if(oShopSaveUserMapper.update(oShopSaveUser) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("修改店铺用户储蓄失败");
        }
        return Result.ok("修改店铺用户储蓄成功");
    }

    /**
     * 删除店铺用户储蓄
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result deleteShopSaveUser(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        ShopSaveUser oShopSaveUser = new ShopSaveUser();
        PoToDTO.poToDto(oShopSaveUserDto,oShopSaveUser);
        if(oShopSaveUserMapper.deleteById(oShopSaveUser.getId()) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("删除店铺用户储蓄失败");
        }
        return Result.ok("删除店铺用户储蓄成功");
    }

    /**
     * 客户充值店铺储蓄
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result rechargeShopSaveUser(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        //获取用户信息
        UserInfo oUserInfo = oUserInfoMapper.selectOneById(oShopSaveUserDto.getUserId());
        if(oUserInfo.getState() == 0){
            return Result.error("用户账号被冻结无法充值");
        }
        //创建业务流水
        FlowBusiness oFlowBusiness = new FlowBusiness();
        oFlowBusiness.setType(1);
        oFlowBusiness.setUserId(oShopSaveUserDto.getUserId());
        oFlowBusiness.setShopId(oShopSaveUserDto.getShopId());
        oFlowBusiness.setInflowDirection(0);
        oFlowBusiness.setInflowWay(0);
        oFlowBusiness.setMoney(oShopSaveUserDto.getRechargePrice());
        if(oFlowBusinessMapper.insert(oFlowBusiness) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("客户充值店铺储蓄失败");
        }
        //创建金额流水
        FlowMoney oFlowMoney = new FlowMoney();
        oFlowMoney.setUserId(oShopSaveUserDto.getUserId());
        oFlowMoney.setShopId(oShopSaveUserDto.getShopId());
        oFlowMoney.setType(1);
        oFlowMoney.setInflowDirection(0);
        oFlowMoney.setInflowWay(0);
        oFlowMoney.setMoney(oShopSaveUserDto.getRechargePrice());
        if(oFlowMoneyMapper.insert(oFlowMoney) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("客户充值店铺储蓄失败");
        }
        return Result.ok(oFlowBusiness.getId());
    }

    /**
     * 客户充值店铺储蓄（回调）
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Map<String, String> rechargeShopSaveUserCallback(JSONObject jsonObject) throws Exception {
        try {
            JSONObject returnObject = oWeiXinPayService.notifyOrder(jsonObject);
            System.out.println("-------------------------------------------");
            System.out.println("回调数据" + returnObject);
            System.out.println("-------------------------------------------");
            String outTradeNo = returnObject.get("out_trade_no").toString();
            String attach = returnObject.get("attach").toString();
            //处理微信流水
            UpdateChain.of(ComPayFlow.class)
                    .set(ComPayFlow::getState, 1)
                    .where(ComPayFlow::getType).eq(1)
                    .where(ComPayFlow::getOrderId).eq(outTradeNo)
                    .update();
            if(StringUtils.isNotBlank(attach)){
                Map<String, String> jsonMap = JSONObject.parseObject(attach, new TypeReference<HashMap<String, String>>() {
                });
                rechargeShopSaveUserCallback(jsonMap.get("userId"),jsonMap.get("shopId"),Double.valueOf(jsonMap.get("rechargePrice")),Double.valueOf(jsonMap.get("giftsPrice")));
            }
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }finally {
            Map<String, String> res = new HashMap<>();
            res.put("code", "SUCCESS");
            res.put("message", "成功");
            return res;
        }
    }

    /**
     * 客户充值店铺储蓄（回调业务逻辑）
     * @param userId 客户ID
     * @param ShopId 店铺ID
     * @param rechargePrice 充值金额
     * @param giftsPrice 赠送金额
     * @return
     * @throws Exception
     */
    @Transactional
    public void rechargeShopSaveUserCallback(String userId, String shopId, Double rechargePrice, Double giftsPrice) throws Exception {
        //修改业务流水
        UpdateChain.of(FlowBusiness.class)
                .set(FlowBusiness::getState, 1)
                .where(FlowBusiness::getUserId).eq(userId)
                .where(FlowBusiness::getShopId).eq(shopId)
                .where(FlowBusiness::getType).eq(1)
                .where(FlowBusiness::getInflowDirection).eq(0)
                .where(FlowBusiness::getInflowWay).eq(0)
                .update();
        //修改金额流水
        UpdateChain.of(FlowMoney.class)
                .set(FlowMoney::getState, 1)
                .where(FlowMoney::getUserId).eq(userId)
                .where(FlowMoney::getShopId).eq(shopId)
                .where(FlowMoney::getType).eq(1)
                .where(FlowMoney::getInflowDirection).eq(0)
                .where(FlowMoney::getInflowWay).eq(0)
                .update();
        //获取用户的信息
        UserInfo oUserInfo = oUserInfoMapper.selectOneById(userId);
        if(StringUtils.isNotBlank(oUserInfo.getInvitationCode())){
            //判断用户是否是新会员
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.USER_ID.eq(userId));
            if(CollectionUtil.isEmpty(oShopSaveUserMapper.selectListByQuery(queryWrapper))){
                //获取用户推荐人信息
                queryWrapper = new QueryWrapper();
                queryWrapper.where(UserInfoTableDef.USER_INFO.ID.eq(oUserInfo.getInvitationCode()));
                queryWrapper.where(UserInfoTableDef.USER_INFO.STATE.eq(1));
                queryWrapper.where(UserInfoTableDef.USER_INFO.IS_DISTRIBUTION.ne(3));
                UserInfo codeUserInfo = oUserInfoMapper.selectOneByQuery(queryWrapper);
                if(codeUserInfo != null){
                    codeUserInfo.setInvitationSaveNum(codeUserInfo.getInvitationSaveNum() + 1);
                    //判断用户是否返利
                    if(codeUserInfo.getIsRebate() == 0){
                        //获取邀请储蓄会员返利人数
                        queryWrapper  = new QueryWrapper();
                        queryWrapper.where(ComVariableTableDef.COM_VARIABLE.SYSTEM_TITLE.eq("invitation_save_num"));
                        ComVariable oComVariable = oComVariableMapper.selectOneByQuery(queryWrapper);
                        if(oComVariable != null && Integer.valueOf(oComVariable.getSystemValues()).compareTo(codeUserInfo.getInvitationSaveNum()) <= 0){
                            //获取邀请储蓄会员返利金额
                            queryWrapper  = new QueryWrapper();
                            queryWrapper.where(ComVariableTableDef.COM_VARIABLE.SYSTEM_TITLE.eq("invitation_save_price"));
                            oComVariable = oComVariableMapper.selectOneByQuery(queryWrapper);
                            if(oComVariable != null){
                                //创建业务流水
                                FlowBusiness oFlowBusiness = new FlowBusiness();
                                oFlowBusiness.setType(5);
                                oFlowBusiness.setUserId(codeUserInfo.getId());
                                oFlowBusiness.setInflowDirection(1);
                                oFlowBusiness.setInflowWay(0);
                                oFlowBusiness.setMoney(Double.valueOf(oComVariable.getSystemValues()));
                                oFlowBusiness.setState(1);
                                if(oFlowBusinessMapper.insert(oFlowBusiness) == 0){
                                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                    throw new Exception("客户充值店铺储蓄失败");
                                }
                                //创建金额流水
                                FlowMoney oFlowMoney = new FlowMoney();
                                oFlowMoney.setType(5);
                                oFlowMoney.setUserId(codeUserInfo.getId());
                                oFlowMoney.setInflowDirection(1);
                                oFlowMoney.setInflowWay(0);
                                oFlowMoney.setMoney(Double.valueOf(oComVariable.getSystemValues()));
                                oFlowMoney.setState(1);
                                if(oFlowMoneyMapper.insert(oFlowMoney) == 0){
                                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                    throw new Exception("客户充值店铺储蓄失败");
                                }
                                //创建执行计划
                                FlowTask oFlowTask = new FlowTask();
                                PoToDTO.poToDto(oFlowMoney,oFlowTask);
                                oFlowTask.setId(null);
                                oFlowTask.setState(null);
                                if(oFlowTaskMapper.insert(oFlowTask) == 0){
                                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                    throw new Exception("客户充值店铺储蓄失败");
                                }
                                codeUserInfo.setIsRebate(1);
                            }
                        }
                    }
                }
                //修改推荐用户信息
                if(oUserInfoMapper.update(codeUserInfo) == 0){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    throw new Exception("客户充值店铺储蓄失败");
                }
            }
        }
        //添加店铺用户储蓄
        ShopSaveUser oShopSaveUser = new ShopSaveUser();
        oShopSaveUser.setShopId(shopId);
        oShopSaveUser.setUserId(userId);
        oShopSaveUser.setUserBalance(rechargePrice + giftsPrice);
        oShopSaveUser.setRechargePrice(rechargePrice);
        oShopSaveUser.setGiftsPrice(giftsPrice);
        oShopSaveUser.setDiscountRatio(rechargePrice / (rechargePrice + giftsPrice));
        if(oShopSaveUserMapper.insert(oShopSaveUser) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new Exception("客户充值店铺储蓄失败");
        }
    }

    /**
     * 获取用户储蓄余额
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getShopSaveUserBalance(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        //获取用户的储蓄余额
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.USER_ID.eq(oShopSaveUserDto.getUserId()));
        queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.SHOP_ID.eq(oShopSaveUserDto.getShopId()));
        queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.IS_SPEND.eq(0));
        queryWrapper.orderBy("create_time,user_balance asc");
        List<ShopSaveUser> oShopSaveUserList = oShopSaveUserMapper.selectListByQuery(queryWrapper);
        Double userBalance = 0.0;
        for(ShopSaveUser oShopSaveUser : oShopSaveUserList){
            userBalance += oShopSaveUser.getUserBalance();
        }
        return Result.ok(userBalance);
    }

    /**
     * 获取用户储蓄店铺
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getShopSaveUserShop(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        QueryWrapper queryWrapper = new QueryWrapper();
        //判断是否传入用户ID
        queryWrapper.select("shop_id");
        queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.USER_ID.eq(oShopSaveUserDto.getUserId()));
        queryWrapper.groupBy("shop_id");
        RelationManager.addQueryRelations("shopInfo");
        RelationManager.setMaxDepth(1);
        List<ShopSaveUser> oShopSaveUserList = oShopSaveUserMapper.selectListWithRelationsByQuery(queryWrapper);
        return Result.ok(oShopSaveUserList,oShopSaveUserList.size());
    }

    /**
     * 获取店铺用户储蓄总额余额
     * @param oShopSaveUserDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getShopSaveUserTotal(ShopSaveUserDto oShopSaveUserDto) throws Exception {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("SUM(user_balance) as userBalance, SUM(recharge_price + gifts_price) as allPrice");
        queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.SHOP_ID.eq(oShopSaveUserDto.getShopId()));
        ShopSaveUser oShopSaveUser = oShopSaveUserMapper.selectOneByQuery(queryWrapper);
        return Result.ok(oShopSaveUser);
    }

}
